const { PointTransaction, PointRule, User } = require('../models');
const { Op } = require('sequelize');
const logger = require('../utils/logger');
const pointRuleService = require('./pointRule.service');

class PointTransactionService {
  /**
   * 创建积分交易
   * @param {Object} data - 积分交易数据
   * @returns {Promise<Object>} - 创建的积分交易
   */
  async createTransaction(data) {
    try {
      // Validate point rule
      const validation = await pointRuleService.validatePointRule(data.ruleId, data.userId);
      if (!validation.valid) {
        throw new Error(`Point rule validation failed: ${validation.reason}`);
      }

      // Create transaction
      const transaction = await PointTransaction.create({
        ...data,
        points: validation.points,
        status: 'completed'
      });

      // Update user's total points
      await User.increment(
        { totalPoints: validation.points },
        { where: { id: data.userId } }
      );

      logger.info(`Point transaction created with ID: ${transaction.id}`);
      return transaction;
    } catch (error) {
      logger.error('Error creating point transaction:', error);
      throw error;
    }
  }

  /**
   * 获取积分交易列表
   * @param {Object} filters - 过滤条件
   * @returns {Promise<Array<Object>>} - 积分交易列表
   */
  async getTransactions(filters = {}) {
    try {
      const where = {};
      if (filters.userId) {
        where.userId = filters.userId;
      }
      if (filters.type) {
        where.type = filters.type;
      }
      if (filters.status) {
        where.status = filters.status;
      }
      if (filters.startDate) {
        where.createdAt = {
          ...where.createdAt,
          [Op.gte]: filters.startDate
        };
      }
      if (filters.endDate) {
        where.createdAt = {
          ...where.createdAt,
          [Op.lte]: filters.endDate
        };
      }

      const transactions = await PointTransaction.findAll({
        where,
        include: [
          {
            model: PointRule,
            attributes: ['name', 'type', 'points']
          },
          {
            model: User,
            attributes: ['id', 'name', 'totalPoints']
          }
        ],
        order: [['createdAt', 'DESC']]
      });
      return transactions;
    } catch (error) {
      logger.error('Error getting point transactions:', error);
      throw error;
    }
  }

  /**
   * 获取积分交易详情
   * @param {number} id - 积分交易ID
   * @returns {Promise<Object>} - 积分交易详情
   */
  async getTransaction(id) {
    try {
      const transaction = await PointTransaction.findByPk(id, {
        include: [
          {
            model: PointRule,
            attributes: ['name', 'type', 'points']
          },
          {
            model: User,
            attributes: ['id', 'name', 'totalPoints']
          }
        ]
      });
      if (!transaction) {
        throw new Error('Point transaction not found');
      }
      return transaction;
    } catch (error) {
      logger.error(`Error getting point transaction with ID ${id}:`, error);
      throw error;
    }
  }

  /**
   * 获取用户积分交易列表
   * @param {number} userId - 用户ID
   * @param {Object} filters - 过滤条件
   * @returns {Promise<Array<Object>>} - 积分交易列表
   */
  async getUserTransactions(userId, filters = {}) {
    try {
      const where = { userId };
      if (filters.type) {
        where.type = filters.type;
      }
      if (filters.startDate) {
        where.createdAt = {
          ...where.createdAt,
          [Op.gte]: filters.startDate
        };
      }
      if (filters.endDate) {
        where.createdAt = {
          ...where.createdAt,
          [Op.lte]: filters.endDate
        };
      }

      const transactions = await PointTransaction.findAll({
        where,
        include: [
          {
            model: PointRule,
            attributes: ['name', 'type', 'points']
          }
        ],
        order: [['createdAt', 'DESC']]
      });
      return transactions;
    } catch (error) {
      logger.error(`Error getting transactions for user ${userId}:`, error);
      throw error;
    }
  }

  /**
   * 取消积分交易
   * @param {number} id - 积分交易ID
   * @returns {Promise<Object>} - 取消的积分交易
   */
  async cancelTransaction(id) {
    try {
      const transaction = await this.getTransaction(id);
      if (transaction.status === 'cancelled') {
        throw new Error('Transaction is already cancelled');
      }

      // Update transaction status
      await transaction.update({ status: 'cancelled' });

      // Revert user's points
      await User.decrement(
        { totalPoints: transaction.points },
        { where: { id: transaction.userId } }
      );

      logger.info(`Point transaction ${id} cancelled successfully`);
      return transaction;
    } catch (error) {
      logger.error(`Error cancelling point transaction ${id}:`, error);
      throw error;
    }
  }

  /**
   * 获取积分统计
   * @param {Object} filters - 过滤条件
   * @returns {Promise<Object>} - 积分统计
   */
  async getPointsStatistics(filters = {}) {
    try {
      const where = {};
      if (filters.userId) {
        where.userId = filters.userId;
      }
      if (filters.startDate) {
        where.createdAt = {
          ...where.createdAt,
          [Op.gte]: filters.startDate
        };
      }
      if (filters.endDate) {
        where.createdAt = {
          ...where.createdAt,
          [Op.lte]: filters.endDate
        };
      }

      // Get total points earned and spent
      const pointsByType = await PointTransaction.findAll({
        where: {
          ...where,
          status: 'completed'
        },
        attributes: [
          'type',
          [PointTransaction.sequelize.fn('SUM', PointTransaction.sequelize.col('points')), 'total']
        ],
        group: ['type']
      });

      // Get daily points activity
      const dailyActivity = await PointTransaction.findAll({
        where: {
          ...where,
          status: 'completed'
        },
        attributes: [
          [PointTransaction.sequelize.fn('DATE', PointTransaction.sequelize.col('createdAt')), 'date'],
          'type',
          [PointTransaction.sequelize.fn('SUM', PointTransaction.sequelize.col('points')), 'points']
        ],
        group: [
          PointTransaction.sequelize.fn('DATE', PointTransaction.sequelize.col('createdAt')),
          'type'
        ],
        order: [
          [PointTransaction.sequelize.fn('DATE', PointTransaction.sequelize.col('createdAt')), 'ASC']
        ]
      });

      // Get points by rule
      const pointsByRule = await PointTransaction.findAll({
        where: {
          ...where,
          status: 'completed'
        },
        attributes: [
          'ruleId',
          [PointTransaction.sequelize.fn('SUM', PointTransaction.sequelize.col('points')), 'total']
        ],
        include: [
          {
            model: PointRule,
            attributes: ['name', 'type']
          }
        ],
        group: ['ruleId', 'PointRule.name', 'PointRule.type']
      });

      return {
        pointsByType,
        dailyActivity,
        pointsByRule
      };
    } catch (error) {
      logger.error('Error getting points statistics:', error);
      throw error;
    }
  }
}

module.exports = new PointTransactionService(); 